package mySerial

import (
	"encoding/hex"
	"fmt"
	"strings"
	"time"

	"go.bug.st/serial"
)

// 获取到串口列表
func SerialList() []string {
	coms, err := serial.GetPortsList()
	if err != nil {
		return coms
	}
	for i, com := range coms {
		fmt.Println(i)
		fmt.Println(com)
	}
	return coms
}

// 打开串口
func SerialOpen() {

}

// 发送串口数据
func SerialSend(Port serial.Port, data []byte) (int, error) {
	sendN, err := Port.Write(data)
	return sendN, err
}

// 计算Modbus CRC16校验值
func Crc16(data []byte) uint16 {
	crc := uint16(0xFFFF)
	for _, b := range data {
		crc ^= uint16(b)
		for i := 0; i < 8; i++ {
			if crc&0x0001 != 0 {
				crc = (crc >> 1) ^ 0xA001
			} else {
				crc >>= 1
			}
		}
	}
	return crc
}

// 添加报文并且485
func AddSendCrc(dataToSend []byte) []byte {
	// dataToSend := []byte{0x01, 0x03, 0x00, 0x00, 0x00, 0x20} // 原始数据（去掉末尾2字节校验位）
	crc := Crc16(dataToSend)

	// 小端序：低字节在前，高字节在后
	lsb := byte(crc & 0xFF)
	msb := byte(crc >> 8)

	// fmt.Printf("原始数据: % X\n", dataToSend)
	// fmt.Printf("计算出的校验位: %02X %02X\n", lsb, msb)
	dataToSend = append(dataToSend, lsb, msb)
	// fmt.Printf("完整报文: % X\n", dataToSend)
	return dataToSend
}

// 转换十六进制字符串到字节切片并添加CRC
func HexStringToBytesWithCRC(input string) ([]byte, error) {
	// 清理字符串（移除空格/空字符）
	cleaned := strings.ReplaceAll(input, " ", "")
	cleaned = strings.ReplaceAll(cleaned, "0x", "")

	// 解码为字节切片
	data, err := hex.DecodeString(cleaned)
	if err != nil {
		return nil, fmt.Errorf("invalid hex string: %v", err)
	}

	// 计算CRC校验位
	crc := Crc16(data)
	// 小端序：低字节在前，高字节在后
	crcBytes := []byte{byte(crc & 0xFF), byte(crc >> 8)}

	// 附加校验位
	return append(data, crcBytes...), nil
}

// 进行写 读 串口数据
func PortSendRead(Port serial.Port, realData []byte) (bool, []byte) {
	sendN, sendErr := Port.Write(realData)
	if sendErr != nil {
		// fmt.Println("sendErr %s", sendErr)
		return false, nil
	}

	if sendN <= 0 {
		// fmt.Println("sendN %d", sendN)
		return false, nil
	}
	// fmt.Println("sendN %d", sendN)
	// fmt.Printf("send date: %s \n", time.Now().Format(".000"))

	var n int
	var readErr error
	// 获取当前时间（精确到毫秒）
	lastTimestamp := time.Now().UnixMilli()
	lastTimestamp = 0

	// 监听并打印接收数据
	buf := make([]byte, 128)

	// 启动goroutine监听停止信号
	// readFlag := make(chan bool)
	ReadBuff := make([]byte, 256)
	ReadWait := false
	ReadRes := false
	ReadLen := 0
	CanTime := 16

	// fmt.Printf("%s %s %s", n, readErr, lastTimestamp, buf)

	go func() {
		for {
			time.Sleep(5 * time.Millisecond)
			// fmt.Println("while read ")
			if ReadLen > 0 && ReadWait == false && ReadRes == false {
				fmt.Printf("bytes: % X  date: %s \n", ReadBuff[0:ReadLen], time.Now().Format(".000"))
				// ReadLen = 0
				lastTimestamp = 0
				CanTime = 0
				ReadRes = true
			}
			if CanTime <= 0 {
				break
			}
			CanTime--
			// if (CanTime >)
		}
	}()

	for {
		n, readErr = Port.Read(buf)
		// fmt.Println("while read uart ")
		if CanTime <= 0 {
			break
		}
		if readErr != nil {
			// fmt.Println("readErr ", readErr)
			continue
		}
		if n == 0 {
			// fmt.Println("n == 0 err ", n)
			continue
		}

		timestamp := time.Now().UnixMilli()
		// 需要拼接
		if timestamp-lastTimestamp <= 5 || lastTimestamp == 0 {
			for i := 0; i < n; i++ {
				ReadBuff[ReadLen+i] = buf[i]
			}
			ReadLen += n
			ReadWait = true
			go func() {
				time.Sleep(15 * time.Millisecond)
				ReadWait = false
			}()
		}
		lastTimestamp = timestamp
		// fmt.Printf("Received %d bytes: % X\n", n, buf[0:n])
	}

	// fmt.Println("\n--------------------")
	if ReadRes {
		fmt.Printf("拿取到了数据进行判断 %X len: %d date: %s \n ", ReadBuff[0:ReadLen], ReadLen, time.Now().Format(".000"))
		// fmt.Println(ReadBuff[0], ReadBuff[1], ReadBuff[2])
		// fmt.Println(realData[0], realData[1], realData[2])

		newSendData := AddSendCrc([]byte{ReadBuff[0], ReadBuff[1], ReadBuff[2], ReadBuff[3], ReadBuff[4]})
		if ReadBuff[0] == realData[0] && ReadBuff[1] == realData[1] && ReadBuff[2] == 0x02 && newSendData[5] == ReadBuff[5] && newSendData[6] == ReadBuff[6] {
			return true, ReadBuff[0:ReadLen]
		}
		return false, nil
	}
	return false, nil
}
